package io.github.wppli.domain.authenticate.service;

import io.github.wppli.domain.authenticate.model.entity.UserEntity;
import io.github.wppli.domain.authenticate.repository.IAuthenticateRepository;
import io.github.wppli.domain.authenticate.service.engine.IMessageLoader;
import io.github.wppli.domain.authenticate.service.engine.factory.AuthenticateFactory;
import io.github.wppli.types.exception.AccountExistException;
import io.github.wppli.types.exception.AppException;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;

import static io.github.wppli.types.enums.ResponseCode.ACCOUNT_EXIST_ERROR;

/**
 * 用户账号相关服务
 * @author li--jiaqiang 2024−12−25
 */
@Service
public class AccountService implements IAccountService {

    private final IAuthenticateRepository userRepository;
    private final AuthenticateFactory authenticateFactory;
    private final PasswordEncoder passwordEncoder;
    public AccountService(IAuthenticateRepository userRepository, AuthenticateFactory authenticateFactory, PasswordEncoder passwordEncoder) {
        this.userRepository = userRepository;
        this.authenticateFactory = authenticateFactory;
        this.passwordEncoder = passwordEncoder;
    }

    @Override
    public UserEntity queryUserInfoByEmail(String email) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        return queryUserInfo(email);
    }

    @Override
    public UserEntity queryUserInfoByPhoneNumber(String phoneNumber) throws InvocationTargetException, NoSuchMethodException, IllegalAccessException {
        return queryUserInfo(phoneNumber);
    }

    private UserEntity queryUserInfo(String value) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {
        // 0. 获取要执行的方法名
        String method = AuthenticateFactory.getDigitalIdentityType(value, AuthenticateFactory.DigitalIdentityType.queryUserInfo);
        // 1. 获取 userRepository 的 Class 对象
        Class<?> repositoryClass = userRepository.getClass();
        // 2. 获取 queryUserInfoWithEmail 方法
        Method queryMethod = repositoryClass.getMethod(method, String.class);
        // 4. 调用 queryUserInfoWithEmail 方法
        return (UserEntity)queryMethod.invoke(userRepository, value);
    }

    @Override
    public void verifyAccountExist(String contactInformation) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {

        // 0. 获取要执行的方法名
        String method = AuthenticateFactory.getDigitalIdentityType(contactInformation, AuthenticateFactory.DigitalIdentityType.queryUserInfo);
        // 1. 获取 userRepository 的 Class 对象
        Class<?> repositoryClass = userRepository.getClass();
        // 2. 获取 queryUserInfoWithEmail 方法
        Method queryMethod = repositoryClass.getMethod(method, String.class);
        // 4. 调用 queryUserInfoWithEmail 方法
        UserEntity userEntity = (UserEntity)queryMethod.invoke(userRepository, contactInformation);

        if (null != userEntity) {
            throw new AccountExistException(ACCOUNT_EXIST_ERROR.getCode(), ACCOUNT_EXIST_ERROR.getInfo());
        }
    }

    @Override
    public void register(String contactInformation, String type) {
        if ("phone".equals(type)) {
            userRepository.registerWithPhoneNumber(contactInformation);
        } else {
            userRepository.registerWithEmail(contactInformation);
        }

    }

    @Override
    public void setPassword(String contactInformation, String password) {
        Map<String, IMessageLoader> messageLoaderMap = authenticateFactory.getMessageLoaderMap();
        AuthenticateFactory.MessageLoaderType messageLoaderType = AuthenticateFactory.getMessageLoaderType(contactInformation);
        IMessageLoader iMessageLoader = messageLoaderMap.get(messageLoaderType.getActuatorName());
        String encodedPassword = passwordEncoder.encode(password);
        iMessageLoader.setPassword(contactInformation, encodedPassword);
    }

    @Override
    public void bindEmailWithUsername(String email, String username) {
        // 判断是否已经绑定
        UserEntity userEntity = userRepository.queryUserInfoByUsername(username);
        if(null != userEntity && !StringUtils.isAnyBlank(userEntity.getEmail())) {
            throw new AppException("邮箱已绑定");
        }
        userRepository.bindEmailWithUsername(email, username);
    }
}